﻿var chatApp = (function ($, moment, Object) {

    Object.defineProperty(Object.prototype, 'toSortedIdArray', {
        value: function () {
            var a = [];
            var b = [];

            for (var chatId in this) {
                if (this.hasOwnProperty(chatId)) {
                    var c = this[chatId];
                    c.id = chatId;
                    var t = new Date(c.timestamp);
                    c.timestamp = t.toString() != "Invalid Date" ? t.toISOString() : new Date('1980-01-01').toISOString();
                    a.push(c);
                }
            }

            a.sort(function (a, b) {
                if (a.timestamp < b.timestamp) {
                    return -1;
                } else if (a.timestamp > b.timestamp) {
                    return 1;
                } else {
                    return 0;
                }
            });

            for (var i = 0; i < a.length; i++) {
                b.push(a[i].id);
            }

            return b;
        }
    });

    //Add a toSortedArray method to the Object Prototype
    //Object.defineProperty(Object.prototype, 'toSortedArray', {
    //    value: function () {
    //        var a = [];
    //        for (var p in this) {
    //            if (this.hasOwnProperty(p)) {
    //                var o = {};
    //                var c = this[p];
    //                var t = new Date(c.timestamp);
    //                c.timestamp = t.toString() != "Invalid Date" ? t.toISOString() : new Date('1980-01-01').toISOString();
    //                o[p] = c;
    //                a.push(o);
    //            }
    //        }

    //        a.sort(function (o1, o2) {
    //            var a = o1[Object.keys(o1)[0]];
    //            var b = o2[Object.keys(o2)[0]];

    //            if (a.timestamp > b.timestamp) {
    //                return -1;
    //            } else if (a.timestamp < b.timestamp) {
    //                return 1;
    //            } else {
    //                return 0;
    //            }
    //        });

    //        return a;
    //    }
    //});

    var chats = {};
    var userName = "Nick";
    var baseUrl = "hccsport";

    //Url Maker helper function
    var urlMaker = function (base) {
        var url = "https://" + base + ".firebaseio.com/chat/"
        for (var i = 1; i < arguments.length; i++) {
            url += arguments[i] + "/"
        }
        return url + ".json";
    }

    var updateTime = function () {
        $('.niceTime').each(function () {
            var chatId = $(this).parent().parent().attr('id');
            $(this).html('<small>' + moment(chats[chatId].fb.timestamp).fromNow() + '</small>');
        })
    }

    var createChatRowHtml = function (data) {
        var chat = data.chat;
        var chatId = data.id;
        var dateString = moment(chat.timestamp).fromNow();
        var h = '<div class="row" id="' + chatId + '">';
        h += '<div class="col-md-7 column"><blockquote>';
        h += '<small>' + chat.user + '</small>';
        h += '<p>' + $('<div/>').html(chat.message).text(); + '</p>';
        h += '</blockquote></div>';
        h += '<div class="col-md-2 column">';
        h += '<p class="text-right niceTime"><small>' + dateString + '</small></p>';
        if (chat.user === userName) {
            h += '<p class="text-right"><input data-id="' + chatId + '" class="deleteCheck hidden" type="checkbox" /></p>';
        }
        h += '</div>';
        h += '</div>';
        return h;
    };
        
    var loadMessages = function (callback) {
        firebaseRequest({
            verb: 'GET',
            url: urlMaker(baseUrl),
            success: callback,
            error: errorCallback
        });
        //$.getJSON(urlMaker(baseUrl), function (data) {
        //    callback(data);
        //});
    }

    var checkForNewMessages = function () {
        loadMessages(function (data) {
            for (var chatId in data) {
                if (!chats[chatId]) {
                    buildAndAnimateChat(chatId, data);
                }
            }

            updateTime();
        });
    }

    var buildAndAnimateChat = function (chatId, data) {
        if (data[chatId]) {
            chats[chatId] = Object.create(null, { fb: { value: data[chatId] } });
        }
        else {
            chats[chatId] = { fb: data };
        }
        var jqObj = $('#chat').prepend(createChatRowHtml(Object.create(null, { id: { value: chatId }, chat: { value: chats[chatId].fb } })));
        chats[chatId].jq = jqObj;

        $((function (chatId) {
            var divId = '#' + chatId;
            return function () {
                $(divId).animate({
                    opacity: 0.25
                }, 500, function () {
                    $(divId).animate({ opacity: 1.0 }, 500);
                });
            }
        })(chatId));
    };

    var start = function () {
        loadMessages(function (data) {
            var sortedChats = data.toSortedIdArray();
            
            for (var i = 0; i < sortedChats.length; i++) {
                //var chatId = Object.keys(sortedChats[i])[0];
                var chatId = sortedChats[i];
                buildAndAnimateChat(chatId, data);
            }

            setInterval(checkForNewMessages, 5000);
        });
    };

    //Edit (actually Delete) functions
    var enableEdit = function () {
        $(".deleteCheck").each(function (index) {
            $(this).toggleClass("hidden");
        });

        toggleButtonDisplay();
    };

    var cancelEdit = function () {
        $(".deleteCheck").each(function (index) {
            $(this).prop("checked", false);
            $(this).toggleClass("hidden");
        });

        toggleButtonDisplay();
    };

    var errorCallback = function (status) {
        alert('Error occurred: ' + status);
    };

    var toggleButtonDisplay = function () {
        $("#enableEdit, #saveEdit, #cancelEdit").toggleClass("hidden");
    }

    var saveEdit = function () {
        var checkedChats = $(".deleteCheck:checked");
        var idArray = $.map(checkedChats, function (element) {
            return $(element).data('id')
        });

        for (var i in idArray) {
            var chatId = idArray[i];

            firebaseRequest({
                verb: 'DELETE',
                url: urlMaker(baseUrl, chatId),
                success: function (data, textStatus) {
                    $("#" + chatId).remove();
                    delete chats[chatId];
                },
                error: errorCallback
            });
            
            //jQuery Ajax
            //$.ajax({
            //    url: urlMaker(baseUrl, chatId),
            //    type: 'DELETE'
            //}).done(function (data, textStatus) {
            //    $("#" + chatId).remove();
            //    delete chats[chatId];
            //});
        }

        $(".deleteCheck").each(function (index) {
            $(this).prop("checked", false);
            $(this).toggleClass("hidden");
        });

        toggleButtonDisplay();
    };

    //Create - (send message)
    var sendMessage = function () {
        var messageText = $('#newMessage').val();

        var newMessage = {
            user: userName,
            message: messageText,
            timestamp: new Date()
        }

        firebaseRequest({
            url: urlMaker(baseUrl),
            verb: 'POST',
            data: newMessage,
            success: function (data) {
                var chatId = data.name;
                buildAndAnimateChat(chatId, newMessage);

                $('#newMessage').val('');
            },
            error: errorCallback
        });
    };

    var firebaseRequest = function (config) {
        var request = new XMLHttpRequest();
        request.open(config.verb, config.url);
        request.onload = function () {
            if (this.status >= '200' && this.status < '400') {
                if (config.success && typeof (config.success) == 'function') {
                    var data = JSON.parse(this.response);
                    config.success(data);
                }
            } else {
                if (config.error && typeof (config.error) == 'function') {
                    config.error(this.status);
                }
            }
        }
        request.onerror = function () {
            if (config.error && typeof (config.error) == 'function') {
                config.error(this.status);
            }
        }

        if (config.data) {
            request.send(JSON.stringify(config.data));            
        } else {
            request.send();
        }
    };
    
    //Build the object the IIFE returns
    return {
        start: start,
        enableEdit: enableEdit,
        cancelEdit: cancelEdit,
        saveEdit: saveEdit,
        sendMessage: sendMessage
    };
})(jQuery, moment, Object);

//'Start' the app
chatApp.start();